#pragma once
#include <iostream>
#include <unordered_map>
#include <unistd.h>
#include "Socket.hpp"
using namespace std;

const int defaultbacklog = 5;

using task_t = function<string(string &)>;

class TcpServer;

class ThreadData
{
public:
    ThreadData(TcpServer *obj_ptr, Socket *sock) : _this(obj_ptr), _sock(sock) {}
    TcpServer *_this;
    Socket *_sock;
};

class TcpServer
{
private:
    static void *ThreadRun(void *args)
    {
        pthread_detach(pthread_self());

        ThreadData *td = static_cast<ThreadData *>(args);
        string message;
        while (true)
        {
            // 1. 读数据
            if (!td->_sock->Recv(message, 4096))
                break;

            // 2. 处理数据
            string res = td->_this->_task(message);
            // 3. 发出数据
            // cout << "要发出的数据：" << res << endl;
            td->_sock->Send(res);

            sleep(1);
        }
        td->_sock->CloseSockFd();
        delete td->_sock;
        delete td;
    }

public:
    TcpServer(int port, task_t task) : _port(port), _listensock(new TcpSocket()), _task(task)
    {
        _listensock->BuildListenSock(port, defaultbacklog);
        cout << "create listenfd: " << _listensock->GetSockFd() << endl;
    }

    void Loop()
    {
        while (true)
        {
            string peerip;
            uint16_t peerport;
            Socket *newsock = _listensock->BuildServerSock(&peerip, &peerport);
            if (newsock)
            {
                pthread_t tid;
                ThreadData *td = new ThreadData(this, newsock);
                pthread_create(&tid, nullptr, ThreadRun, td);

                // cout << "create newsock, sockfd : " << newsock->GetSockFd() << endl;
                // newsock->CloseSockFd();
                // delete newsock;
            }
        }
    }

    // void RegistrationBusiness(const string &key, task_t val)
    // {
    //     _messions.insert(make_pair(key, val));
    // }

    ~TcpServer()
    {
        _listensock->CloseSockFd();
        delete _listensock;
    }

private:
    int _port;
    Socket *_listensock;

    task_t _task;
    // unordered_map<string, task_t> _messions;
};